home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / util / lev_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  31.1 KB  |  1,412 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)lev_main.c    3.1    93/07/10    */
  2. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the main function for the parser
  7.  * and some useful functions needed by yacc
  8.  */
  9.  
  10. #include "hack.h"
  11. #include "sp_lev.h"
  12. #ifdef STRICT_REF_DEF
  13. #include "termcap.h"
  14. #endif
  15.  
  16. #ifdef MAC
  17. # ifdef applec
  18. #  define MPWTOOL
  19. #  include <CursorCtl.h>
  20. # endif
  21. #endif
  22.  
  23. #ifndef MPWTOOL
  24. # define SpinCursor(x)
  25. #endif
  26.  
  27. #ifndef O_WRONLY
  28. # include <fcntl.h>
  29. #endif
  30. #ifndef O_CREAT    /* some older BSD systems do not define O_CREAT in <fcntl.h> */
  31. # include <sys/file.h>
  32. #endif
  33. #ifndef O_BINARY    /* used for micros, no-op for others */
  34. # define O_BINARY 0
  35. #endif
  36.  
  37. #define NEWLINE    10    /* under Mac MPW C '\n' is 13 so don't use it. */
  38.  
  39. #define ERR        (-1)
  40.  
  41. #define NewTab(type, size)    (type **) alloc(sizeof(type *) * size)
  42. #define Free(ptr)        if(ptr) free((genericptr_t) (ptr))
  43. #define Write(fd, item, size)    (void) write(fd, (genericptr_t)(item), size)
  44.  
  45. #ifdef MICRO
  46. # undef exit
  47. # ifndef AMIGA
  48. extern void FDECL(exit, (int));
  49. # endif
  50. #endif
  51.  
  52. #define MAX_ERRORS    25
  53.  
  54. extern int  NDECL (yyparse);
  55. extern void FDECL (init_yyin, (FILE *));
  56. extern void FDECL (init_yyout, (FILE *));
  57.  
  58. int  FDECL (main, (int, char **));
  59. void FDECL (yyerror, (const char *));
  60. void FDECL (yywarning, (const char *));
  61. int  NDECL (yywrap);
  62. char *FDECL(dup_string,(const char *));
  63. int FDECL(get_floor_type, (CHAR_P));
  64. int FDECL(get_room_type, (char *));
  65. int FDECL(get_trap_type, (char *));
  66. int FDECL(get_monster_id, (char *, CHAR_P));
  67. int FDECL(get_object_id, (char *));
  68. boolean FDECL(check_monster_char, (CHAR_P));
  69. boolean FDECL(check_object_char, (CHAR_P));
  70. char FDECL(what_map_char, (CHAR_P));
  71. void FDECL(scan_map, (char *));
  72. void NDECL(wallify_map);
  73. boolean NDECL(check_subrooms);
  74. void FDECL(check_coord, (int, int, const char *));
  75. void NDECL(store_part);
  76. void NDECL(store_room);
  77. static void FDECL(write_common_data, (int,int,lev_init *,long));
  78. void FDECL(write_maze, (int, specialmaze *));
  79. void FDECL(write_lev, (int, splev *));
  80. void FDECL(free_rooms, (room **, int));
  81.  
  82. static struct {
  83.     const char *name;
  84.     int type;
  85. } trap_types[] = {
  86.     { "arrow",    ARROW_TRAP },
  87.     { "dart",    DART_TRAP },
  88.     { "falling rock", ROCKTRAP },
  89.     { "board",    SQKY_BOARD },
  90.     { "bear",    BEAR_TRAP },
  91.     { "land mine",    LANDMINE },
  92.     { "sleep gas",    SLP_GAS_TRAP },
  93.     { "rust",    RUST_TRAP },
  94.     { "fire",    FIRE_TRAP },
  95.     { "pit",    PIT },
  96.     { "spiked pit",    SPIKED_PIT },
  97.     { "trapdoor",    TRAPDOOR },
  98.     { "teleport",    TELEP_TRAP },
  99.     { "level teleport", LEVEL_TELEP },
  100.     { "magic portal",   MAGIC_PORTAL },
  101.     { "web",    WEB },
  102.     { "statue",    STATUE_TRAP },
  103.     { "magic",    MAGIC_TRAP },
  104.     { "anti magic",    ANTI_MAGIC },
  105. #ifndef POLYSELF
  106. #define POLY_TRAP NO_TRAP    /* this will result in a random trap */
  107. #endif
  108.     { "polymorph",    POLY_TRAP },
  109.     { 0, 0 }
  110. };
  111.  
  112. static struct {
  113.     const char *name;
  114.     int type;
  115. } room_types[] = {
  116.     /* for historical reasons, room types are not contiguous numbers */
  117.     /* (type 1 is skipped) */
  118.     { "ordinary",     OROOM },
  119.     { "throne",     COURT },
  120.     { "swamp",     SWAMP },
  121.     { "vault",     VAULT },
  122.     { "beehive",     BEEHIVE },
  123.     { "morgue",     MORGUE },
  124. #ifdef ARMY
  125.     { "barracks",     BARRACKS },
  126. #endif
  127.     { "zoo",     ZOO },
  128.     { "delphi",     DELPHI },
  129.     { "temple",     TEMPLE },
  130.     { "shop",     SHOPBASE },
  131.     { "armor shop",     ARMORSHOP },
  132.     { "scroll shop", SCROLLSHOP },
  133.     { "potion shop", POTIONSHOP },
  134.     { "weapon shop", WEAPONSHOP },
  135.     { "food shop",     FOODSHOP },
  136.     { "ring shop",     RINGSHOP },
  137.     { "wand shop",     WANDSHOP },
  138.     { "tool shop",     TOOLSHOP },
  139.     { "book shop",     BOOKSHOP },
  140.     { "candle shop", CANDLESHOP },
  141.     { 0, 0 }
  142. };
  143.  
  144. const char *fname = "(stdin)";
  145. int fatal_error = 0;
  146. int want_warnings = 0;
  147.  
  148. #ifdef FLEX23_BUG
  149. /* Flex 2.3 bug work around; not needed for 2.3.6 or later */
  150. int yy_more_len = 0;
  151. #endif
  152.  
  153. extern char tmpmessage[];
  154. extern altar *tmpaltar[];
  155. extern lad *tmplad[];
  156. extern stair *tmpstair[];
  157. extern digpos *tmpdig[];
  158. extern digpos *tmppass[];
  159. extern char *tmpmap[];
  160. extern region *tmpreg[];
  161. extern lev_region *tmplreg[];
  162. extern door *tmpdoor[];
  163. extern room_door *tmprdoor[];
  164. extern trap *tmptrap[];
  165. extern monster *tmpmonst[];
  166. extern object *tmpobj[];
  167. extern drawbridge *tmpdb[];
  168. extern walk *tmpwalk[];
  169. extern gold *tmpgold[];
  170. extern fountain *tmpfountain[];
  171. extern sink *tmpsink[];
  172. extern pool *tmppool[];
  173. extern engraving *tmpengraving[];
  174. extern mazepart *tmppart[];
  175. extern room *tmproom[];
  176. extern corridor *tmpcor[];
  177.  
  178. extern int n_olist, n_mlist, n_plist;
  179.  
  180. extern unsigned int nlreg, nreg, ndoor, ntrap, nmons, nobj;
  181. extern unsigned int ndb, nwalk, npart, ndig, npass, nlad, nstair;
  182. extern unsigned int naltar, ncorridor, nrooms, ngold, nengraving;
  183. extern unsigned int nfountain, npool, nsink;
  184.  
  185. extern unsigned int max_x_map, max_y_map;
  186.  
  187. extern int line_number, colon_line_number;
  188.  
  189. int
  190. main(argc, argv)
  191. int argc;
  192. char **argv;
  193. {
  194.     FILE *fin;
  195.     int i;
  196. #ifdef THINK_C
  197.     static char *mac_argv[] = {    "lev_comp",    /* dummy argv[0] */
  198.                 ":dat:Arch.des",
  199.                 ":dat:Barb.des",
  200.                 ":dat:Caveman.des",
  201.                 ":dat:Elf.des",
  202.                 ":dat:Healer.des",
  203.                 ":dat:Knight.des",
  204.                 ":dat:Priest.des",
  205.                 ":dat:Rogue.des",
  206.                 ":dat:Samurai.des",
  207.                 ":dat:Tourist.des",
  208.                 ":dat:Valkyrie.des",
  209.                 ":dat:Wizard.des",
  210.                 ":dat:bigroom.des",
  211.                 ":dat:castle.des",
  212.                 ":dat:endgame.des",
  213.                 ":dat:gehennom.des",
  214.                 ":dat:knox.des",
  215.                 ":dat:medusa.des",
  216.                 ":dat:mines.des",
  217.                 ":dat:oracle.des",
  218.                 ":dat:tower.des",
  219.                 ":dat:yendor.des"
  220.                 };
  221.  
  222.     argc = SIZE(mac_argv);
  223.     argv = mac_argv;
  224. #endif
  225.     /* Note:  these initializers don't do anything except guarantee that
  226.         we're linked properly.
  227.     */
  228.     monst_init();
  229.     objects_init();
  230.     decl_init();
  231.  
  232.     init_yyout(stdout);
  233.     if (argc == 1) {        /* Read standard input */
  234.         init_yyin(stdin);
  235.         yyparse();
  236.     } else {            /* Otherwise every argument is a filename */
  237.         for(i=1; i<argc; i++) {
  238.             fname = argv[i];
  239.             if(!strcmp(fname, "-w")) {
  240.             want_warnings++;
  241.             continue;
  242.             }
  243.             fin = freopen(fname, "r", stdin);
  244.             if (!fin) {
  245.             (void) fprintf(stderr,"Can't open \"%s\" for input.\n",
  246.                         fname);
  247.             perror(fname);
  248.             } else {
  249.             init_yyin(fin);
  250.             yyparse();
  251.             }
  252.             line_number = 1;
  253.             fatal_error = 0;
  254.         }
  255.     }
  256. #ifndef VMS
  257.     return 0;
  258. #else
  259.     return 1;       /* vms success */
  260. #endif /*VMS*/
  261. }
  262.  
  263. /*
  264.  * Each time the parser detects an error, it uses this function.
  265.  * Here we take count of the errors. To continue farther than
  266.  * MAX_ERRORS wouldn't be reasonable.
  267.  * Assume that explicit calls from lev_comp.y have the 1st letter
  268.  * capitalized, to allow printing of the line containing the start of
  269.  * the current declaration, instead of the beginning of the next declaration.
  270.  */
  271.  
  272. void
  273. yyerror(s)
  274. const char *s;
  275. {
  276.     (void) fprintf(stderr, "%s: line %d : %s\n", fname,
  277.         (*s >= 'A' && *s <= 'Z') ? colon_line_number : line_number, s);
  278.     if (++fatal_error > MAX_ERRORS) {
  279.         (void) fprintf(stderr,"Too many errors, good bye!\n");
  280.         exit(1);
  281.     }
  282. }
  283.  
  284. /*
  285.  * Just display a warning (that is : a non fatal error)
  286.  */
  287.  
  288. void
  289. yywarning(s)
  290. const char *s;
  291. {
  292.     (void) fprintf(stderr, "%s: line %d : WARNING : %s\n",
  293.                 fname, colon_line_number, s);
  294. }
  295.  
  296. int
  297. yywrap()
  298. {
  299.     return 1;
  300. }
  301.  
  302. /*
  303.  * Duplicate a string.
  304.  */
  305.  
  306. char *
  307. dup_string(s)
  308. const char *s;
  309. {
  310.     char *news;
  311.  
  312.     if (!s)
  313.         return (char *) 0;
  314.     news = (char *) alloc(strlen(s)+1);
  315.     Strcpy(news, s);
  316.     return news;
  317. }
  318.  
  319. /*
  320.  * Find the type of floor, knowing its char representation.
  321.  */
  322.  
  323. int
  324. get_floor_type(c)
  325. char c;
  326. {
  327.     int val;
  328.  
  329.     SpinCursor(3);
  330.     val = what_map_char(c);
  331.     if(val == INVALID_TYPE) {
  332.         val = ERR;
  333.         yywarning("Invalid fill character in MAZE declaration");
  334.     }
  335.     return val;
  336. }
  337.  
  338. /*
  339.  * Find the type of a room in the table, knowing its name.
  340.  */
  341.  
  342. int
  343. get_room_type(s)
  344. char *s;
  345. {
  346.     register int i;
  347.  
  348.     SpinCursor(3);
  349.     for(i=0; room_types[i].name; i++)
  350.         if (!strcmp(s, room_types[i].name))
  351.         return ((int) room_types[i].type);
  352.     return ERR;
  353. }
  354.  
  355. /*
  356.  * Find the type of a trap in the table, knowing its name.
  357.  */
  358.  
  359. int
  360. get_trap_type(s)
  361. char *s;
  362. {
  363.     register int i;
  364.  
  365.     SpinCursor(3);
  366.     for (i=0; trap_types[i].name; i++)
  367.         if(!strcmp(s,trap_types[i].name))
  368.         return trap_types[i].type;
  369.     return ERR;
  370. }
  371.  
  372. /*
  373.  * Find the index of a monster in the table, knowing its name.
  374.  */
  375. int
  376. get_monster_id(s, c)
  377. char *s;
  378. char c;
  379. {
  380.     register int i, class;
  381.  
  382.     SpinCursor(3);
  383.     class = def_char_to_monclass(c);
  384.     if (c && class == MAXMCLASSES) return ERR;
  385.  
  386.     for(i = 0; i < NUMMONS; i++)
  387.         if(!strncmp(s, mons[i].mname, strlen(mons[i].mname))
  388.            && (!c || class == mons[i].mlet))
  389.         return i;
  390.     return ERR;
  391. }
  392.  
  393. /*
  394.  * Find the index of an object in the table, knowing its name.
  395.  */
  396. int
  397. get_object_id(s)
  398. char *s;
  399. {
  400.     register int i;
  401.     register const char *objname;
  402.  
  403.     SpinCursor(3);
  404.     for (i=0; i<=NROFOBJECTS; i++)
  405.         if ((objname = obj_descr[i].oc_name)
  406.            && !strncmp(s, objname, strlen(objname)))
  407.         return i;
  408.     return ERR;
  409. }
  410.  
  411. /*
  412.  * Is the character 'c' a valid monster class ?
  413.  */
  414. boolean
  415. check_monster_char(c)
  416. char c;
  417. {
  418.     return (def_char_to_monclass(c) != MAXMCLASSES);
  419. }
  420.  
  421. /*
  422.  * Is the character 'c' a valid object class ?
  423.  */
  424. boolean
  425. check_object_char(c)
  426. char c;
  427. {
  428.     return (def_char_to_objclass(c) != MAXOCLASSES);
  429. }
  430.  
  431. char
  432. what_map_char(c)
  433.  
  434.      char    c;
  435. {
  436.     SpinCursor(3);
  437.     switch(c) {
  438.           case ' '  : return(STONE);
  439.           case '#'  : return(CORR);
  440.           case '.'  : return(ROOM);
  441.           case '-'  : return(HWALL);
  442.           case '|'  : return(VWALL);
  443.           case '+'  : return(DOOR);
  444.           case 'A'  : return(AIR);
  445.           case 'B'  : return(CROSSWALL); /* hack: boundary location */
  446.           case 'C'  : return(CLOUD);
  447.           case 'S'  : return(SDOOR);
  448.           case 'H'  : return(SCORR);
  449.           case '{'  : return(FOUNTAIN);
  450.           case '\\' : return(THRONE);
  451.           case 'K'  :
  452. #ifdef SINKS
  453.               return(SINK);
  454. #else
  455.               yywarning("Sinks are not allowed in this version!  Ignoring...");
  456.               return(ROOM);
  457. #endif
  458.           case '}'  : return(MOAT);
  459.           case 'P'  : return(POOL);
  460.           case 'L'  : return(LAVAPOOL);
  461.           case 'I'  : return(ICE);
  462.           case 'W'  : return(WATER);
  463.         }
  464.     return(INVALID_TYPE);
  465. }
  466.  
  467. /*
  468.  * Yep! LEX gives us the map in a raw mode.
  469.  * Just analyze it here.
  470.  */
  471.  
  472. void
  473. scan_map(map)
  474. char *map;
  475. {
  476.     register int i, len;
  477.     register char *s1, *s2;
  478.     int max_len = 0;
  479.     int max_hig = 0;
  480.     char msg[256];
  481.  
  482.     /* First : find the max width of the map */
  483.  
  484.     s1 = map;
  485.     while (s1 && *s1) {
  486.         s2 = index(s1, NEWLINE);
  487.         if (s2) {
  488.             if (s2-s1 > max_len)
  489.                 max_len = s2-s1;
  490.             s1 = s2 + 1;
  491.         } else {
  492.             if (strlen(s1) > max_len)
  493.                 max_len = strlen(s1);
  494.             s1 = (char *) 0;
  495.         }
  496.     }
  497.  
  498.     /* Then parse it now */
  499.  
  500.     while (map && *map) {
  501.         tmpmap[max_hig] = (char *) alloc(max_len);
  502.         s1 = index(map, NEWLINE);
  503.         if (s1) {
  504.             len = s1 - map;
  505.             s1++;
  506.         } else {
  507.             len = strlen(map);
  508.             s1 = map + len;
  509.         }
  510.         for(i=0; i<len; i++)
  511.           if((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) {
  512.               Sprintf(msg,
  513.              "Invalid character @ (%d, %d) - replacing with stone",
  514.                   max_hig, i);
  515.               yywarning(msg);
  516.               tmpmap[max_hig][i] = STONE;
  517.             }
  518.         while(i < max_len)
  519.             tmpmap[max_hig][i++] = STONE;
  520.         map = s1;
  521.         max_hig++;
  522.     }
  523.  
  524.     /* Memorize boundaries */
  525.  
  526.     max_x_map = max_len - 1;
  527.     max_y_map = max_hig - 1;
  528.  
  529.     /* Store the map into the mazepart structure */
  530.  
  531.     if(max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
  532.         Sprintf(msg, "Map too large! (max %d x %d)", MAP_X_LIM, MAP_Y_LIM);
  533.         yyerror(msg);
  534.     }
  535.  
  536.     tmppart[npart]->xsize = max_len;
  537.     tmppart[npart]->ysize = max_hig;
  538.     tmppart[npart]->map = (char **) alloc(max_hig*sizeof(char *));
  539.     for(i = 0; i< max_hig; i++)
  540.         tmppart[npart]->map[i] = tmpmap[i];
  541. }
  542.  
  543. /*
  544.  *    If we have drawn a map without walls, this allows us to
  545.  *    auto-magically wallify it.
  546.  */
  547. #define Map_point(x,y) *(tmppart[npart]->map[y] + x)
  548. #define Valid_point(x,y) ((x >= 0 && x <= max_x_map) && \
  549.               (y >= 0 && y <= max_y_map))
  550. void
  551. wallify_map()
  552. {
  553.  
  554.     int x, y, xx, yy;
  555.  
  556.     for(y = 0; y <= max_y_map; y++) {
  557.       SpinCursor(3);
  558.       for(x = 0; x <= max_x_map; x++)
  559.  
  560.         if(Map_point(x,y) == STONE) {
  561.  
  562.           for(yy = y - 1; yy <= y+1 && Map_point(x,y) == STONE; yy++)
  563.         for(xx = x - 1; xx <= x+1 && Map_point(x,y) == STONE; xx++)
  564.  
  565.           if(Valid_point(xx,yy) &&
  566.              (IS_ROOM(Map_point(xx,yy)) ||
  567.               Map_point(xx,yy) == CROSSWALL)) {
  568.  
  569.             if(yy != y)    Map_point(x,y) = HWALL;
  570.             else    Map_point(x,y) = VWALL;
  571.           }
  572.         }
  573.     }
  574. }
  575.  
  576. /*
  577.  * We need to check the subrooms apartenance to an existing room.
  578.  */
  579.  
  580. boolean
  581. check_subrooms()
  582. {
  583.     short i,j;
  584.     boolean found, ok = TRUE;
  585.     char msg[256];
  586.  
  587.     for (i = 0; i < nrooms; i++)
  588.         if (tmproom[i]->parent) {
  589.             found = FALSE;
  590.             for(j = 0; j < nrooms; j++)
  591.             if (tmproom[j]->name && !strcmp(tmproom[i]->parent,
  592.                             tmproom[j]->name)) {
  593.                 found = TRUE;
  594.                 break;
  595.             }
  596.             if (!found) {
  597.                 Sprintf(msg,"Subroom error : parent room '%s' not found!", tmproom[i]->parent);
  598.                 yyerror(msg);
  599.                 ok = FALSE;
  600.             }
  601.         }
  602.     return ok;
  603. }
  604.  
  605. /*
  606.  * Check that coordinates (x,y) are roomlike locations.
  607.  * Print warning "str" if they aren't.
  608.  */
  609.  
  610. void
  611. check_coord(x, y, str)
  612. int x, y;
  613. const char *str;
  614. {
  615.     char ebuf[60];
  616.  
  617.     if (x >= 0 && y >= 0 && x <= max_x_map && y <= max_y_map &&
  618.     (IS_ROCK(tmpmap[y][x]) || IS_DOOR(tmpmap[y][x]))) {
  619.     Sprintf(ebuf, "%s placed in wall at (%02d,%02d)?!", str, x, y);
  620.     yywarning(ebuf);
  621.     }
  622. }
  623.  
  624. /*
  625.  * Here we want to store the maze part we just got.
  626.  */
  627.  
  628. void
  629. store_part()
  630. {
  631.     register int i;
  632.  
  633.     /* Ok, We got the whole part, now we store it. */
  634.  
  635.     /* The Regions */
  636.  
  637.     if ((tmppart[npart]->nreg = nreg) != 0) {
  638.         tmppart[npart]->regions = NewTab(region, nreg);
  639.         for(i=0;i<nreg;i++)
  640.             tmppart[npart]->regions[i] = tmpreg[i];
  641.     }
  642.     nreg = 0;
  643.  
  644.     /* The Level Regions */
  645.  
  646.     if ((tmppart[npart]->nlreg = nlreg) != 0) {
  647.         tmppart[npart]->lregions = NewTab(lev_region, nlreg);
  648.         for(i=0;i<nlreg;i++)
  649.             tmppart[npart]->lregions[i] = tmplreg[i];
  650.     }
  651.     nlreg = 0;
  652.  
  653.     /* the doors */
  654.  
  655.     if ((tmppart[npart]->ndoor = ndoor) != 0) {
  656.         tmppart[npart]->doors = NewTab(door, ndoor);
  657.         for(i=0;i<ndoor;i++)
  658.             tmppart[npart]->doors[i] = tmpdoor[i];
  659.     }
  660.     ndoor = 0;
  661.  
  662.     /* the traps */
  663.  
  664.     if ((tmppart[npart]->ntrap = ntrap) != 0) {
  665.         tmppart[npart]->traps = NewTab(trap, ntrap);
  666.         for(i=0;i<ntrap;i++)
  667.             tmppart[npart]->traps[i] = tmptrap[i];
  668.     }
  669.     ntrap = 0;
  670.  
  671.     /* the monsters */
  672.  
  673.     if ((tmppart[npart]->nmonster = nmons) != 0) {
  674.         tmppart[npart]->monsters = NewTab(monster, nmons);
  675.         for(i=0;i<nmons;i++)
  676.             tmppart[npart]->monsters[i] = tmpmonst[i];
  677.     }
  678.     nmons = 0;
  679.  
  680.     /* the objects */
  681.  
  682.     if ((tmppart[npart]->nobject = nobj) != 0) {
  683.         tmppart[npart]->objects = NewTab(object, nobj);
  684.         for(i=0;i<nobj;i++)
  685.             tmppart[npart]->objects[i] = tmpobj[i];
  686.     }
  687.     nobj = 0;
  688.  
  689.     /* the drawbridges */
  690.  
  691.     if ((tmppart[npart]->ndrawbridge = ndb) != 0) {
  692.         tmppart[npart]->drawbridges = NewTab(drawbridge, ndb);
  693.         for(i=0;i<ndb;i++)
  694.             tmppart[npart]->drawbridges[i] = tmpdb[i];
  695.     }
  696.     ndb = 0;
  697.  
  698.     /* The walkmaze directives */
  699.  
  700.     if ((tmppart[npart]->nwalk = nwalk) != 0) {
  701.         tmppart[npart]->walks = NewTab(walk, nwalk);
  702.         for(i=0;i<nwalk;i++)
  703.             tmppart[npart]->walks[i] = tmpwalk[i];
  704.     }
  705.     nwalk = 0;
  706.  
  707.     /* The non_diggable directives */
  708.  
  709.     if ((tmppart[npart]->ndig = ndig) != 0) {
  710.         tmppart[npart]->digs = NewTab(digpos, ndig);
  711.         for(i=0;i<ndig;i++)
  712.             tmppart[npart]->digs[i] = tmpdig[i];
  713.     }
  714.     ndig = 0;
  715.  
  716.     /* The non_passwall directives */
  717.  
  718.     if ((tmppart[npart]->npass = npass) != 0) {
  719.         tmppart[npart]->passs = NewTab(digpos, npass);
  720.         for(i=0;i<npass;i++)
  721.             tmppart[npart]->passs[i] = tmppass[i];
  722.     }
  723.     npass = 0;
  724.  
  725.     /* The ladders */
  726.  
  727.     if ((tmppart[npart]->nlad = nlad) != 0) {
  728.         tmppart[npart]->lads = NewTab(lad, nlad);
  729.         for(i=0;i<nlad;i++)
  730.             tmppart[npart]->lads[i] = tmplad[i];
  731.     }
  732.     nlad = 0;
  733.  
  734.     /* The stairs */
  735.  
  736.     if ((tmppart[npart]->nstair = nstair) != 0) {
  737.         tmppart[npart]->stairs = NewTab(stair, nstair);
  738.         for(i=0;i<nstair;i++)
  739.             tmppart[npart]->stairs[i] = tmpstair[i];
  740.     }
  741.     nstair = 0;
  742.  
  743.     /* The altars */
  744.     if ((tmppart[npart]->naltar = naltar) != 0) {
  745.         tmppart[npart]->altars = NewTab(altar, naltar);
  746.         for(i=0;i<naltar;i++)
  747.             tmppart[npart]->altars[i] = tmpaltar[i];
  748.     }
  749.     naltar = 0;
  750.  
  751.     /* The gold piles */
  752.  
  753.     if ((tmppart[npart]->ngold = ngold) != 0) {
  754.         tmppart[npart]->golds = NewTab(gold, ngold);
  755.         for(i=0;i<ngold;i++)
  756.             tmppart[npart]->golds[i] = tmpgold[i];
  757.     }
  758.     ngold = 0;
  759.  
  760.     /* The engravings */
  761.  
  762.     if ((tmppart[npart]->nengraving = nengraving) != 0) {
  763.         tmppart[npart]->engravings = NewTab(engraving, nengraving);
  764.         for(i=0;i<nengraving;i++)
  765.             tmppart[npart]->engravings[i] = tmpengraving[i];
  766.     }
  767.     nengraving = 0;
  768.  
  769.     /* The fountains */
  770.  
  771.     if ((tmppart[npart]->nfountain = nfountain) != 0) {
  772.         tmppart[npart]->fountains = NewTab(fountain, nfountain);
  773.         for(i=0;i<nfountain;i++)
  774.             tmppart[npart]->fountains[i] = tmpfountain[i];
  775.     }
  776.     nfountain = 0;
  777.  
  778.     npart++;
  779.     n_plist = n_mlist = n_olist = 0;
  780. }
  781.  
  782. /*
  783.  * Here we want to store the room part we just got.
  784.  */
  785.  
  786. void
  787. store_room()
  788. {
  789.     register int i;
  790.  
  791.     /* Ok, We got the whole room, now we store it. */
  792.  
  793.     /* the doors */
  794.  
  795.     if ((tmproom[nrooms]->ndoor = ndoor) != 0) {
  796.         tmproom[nrooms]->doors = NewTab(room_door, ndoor);
  797.         for(i=0;i<ndoor;i++)
  798.             tmproom[nrooms]->doors[i] = tmprdoor[i];
  799.     }
  800.     ndoor = 0;
  801.  
  802.     /* the traps */
  803.  
  804.     if ((tmproom[nrooms]->ntrap = ntrap) != 0) {
  805.         tmproom[nrooms]->traps = NewTab(trap, ntrap);
  806.         for(i=0;i<ntrap;i++)
  807.             tmproom[nrooms]->traps[i] = tmptrap[i];
  808.     }
  809.     ntrap = 0;
  810.  
  811.     /* the monsters */
  812.  
  813.     if ((tmproom[nrooms]->nmonster = nmons) != 0) {
  814.         tmproom[nrooms]->monsters = NewTab(monster, nmons);
  815.         for(i=0;i<nmons;i++)
  816.             tmproom[nrooms]->monsters[i] = tmpmonst[i];
  817.     }
  818.     nmons = 0;
  819.  
  820.     /* the objects */
  821.  
  822.     if ((tmproom[nrooms]->nobject = nobj) != 0) {
  823.         tmproom[nrooms]->objects = NewTab(object, nobj);
  824.         for(i=0;i<nobj;i++)
  825.             tmproom[nrooms]->objects[i] = tmpobj[i];
  826.     }
  827.     nobj = 0;
  828.  
  829.     /* The stairs */
  830.  
  831.     if ((tmproom[nrooms]->nstair = nstair) != 0) {
  832.         tmproom[nrooms]->stairs = NewTab(stair, nstair);
  833.         for(i=0;i<nstair;i++)
  834.             tmproom[nrooms]->stairs[i] = tmpstair[i];
  835.     }
  836.     nstair = 0;
  837.  
  838.     /* The altars */
  839.     if ((tmproom[nrooms]->naltar = naltar) != 0) {
  840.         tmproom[nrooms]->altars = NewTab(altar, naltar);
  841.         for(i=0;i<naltar;i++)
  842.             tmproom[nrooms]->altars[i] = tmpaltar[i];
  843.     }
  844.     naltar = 0;
  845.  
  846.     /* The gold piles */
  847.  
  848.     if ((tmproom[nrooms]->ngold = ngold) != 0) {
  849.         tmproom[nrooms]->golds = NewTab(gold, ngold);
  850.         for(i=0;i<ngold;i++)
  851.             tmproom[nrooms]->golds[i] = tmpgold[i];
  852.     }
  853.     ngold = 0;
  854.  
  855.     /* The engravings */
  856.  
  857.     if ((tmproom[nrooms]->nengraving = nengraving) != 0) {
  858.         tmproom[nrooms]->engravings = NewTab(engraving, nengraving);
  859.         for(i=0;i<nengraving;i++)
  860.             tmproom[nrooms]->engravings[i] = tmpengraving[i];
  861.     }
  862.     nengraving = 0;
  863.  
  864.     /* The fountains */
  865.  
  866.     if ((tmproom[nrooms]->nfountain = nfountain) != 0) {
  867.         tmproom[nrooms]->fountains = NewTab(fountain, nfountain);
  868.         for(i=0;i<nfountain;i++)
  869.             tmproom[nrooms]->fountains[i] = tmpfountain[i];
  870.     }
  871.     nfountain = 0;
  872.  
  873.     /* The sinks */
  874.  
  875.     if ((tmproom[nrooms]->nsink = nsink) != 0) {
  876.         tmproom[nrooms]->sinks = NewTab(sink, nsink);
  877.         for(i=0;i<nsink;i++)
  878.             tmproom[nrooms]->sinks[i] = tmpsink[i];
  879.     }
  880.     nsink = 0;
  881.  
  882.     /* The pools */
  883.  
  884.     if ((tmproom[nrooms]->npool = npool) != 0) {
  885.         tmproom[nrooms]->pools = NewTab(pool, npool);
  886.         for(i=0;i<npool;i++)
  887.             tmproom[nrooms]->pools[i] = tmppool[i];
  888.     }
  889.     npool = 0;
  890.  
  891.     nrooms++;
  892. }
  893.  
  894. /* some info common to all special levels */
  895. static void
  896. write_common_data(fd, typ, init, flgs)
  897. int fd, typ;
  898. lev_init *init;
  899. long flgs;
  900. {
  901.     char c;
  902.     uchar len;
  903.  
  904.     c = typ;
  905.     Write(fd, &c, sizeof(c));    /* 1 byte header */
  906.     Write(fd, init, sizeof(lev_init));
  907.     Write(fd, &flgs, sizeof flgs);
  908.  
  909.     len = strlen(tmpmessage);
  910.     Write(fd, &len, sizeof len);
  911.     if (len) Write(fd, tmpmessage, (int) len);
  912.     tmpmessage[0] = '\0';
  913. }
  914.  
  915. /*
  916.  * Here we write the structure of the maze in the specified file (fd).
  917.  * Also, we have to free the memory allocated via alloc()
  918.  */
  919.  
  920. void
  921. write_maze(fd, maze)
  922. int fd;
  923. specialmaze *maze;
  924. {
  925.     short i,j;
  926.     mazepart *pt;
  927.  
  928.     write_common_data(fd, SP_LEV_MAZE, &(maze->init_lev), maze->flags);
  929.  
  930.     Write(fd, &(maze->filling), sizeof(maze->filling));
  931.     Write(fd, &(maze->numpart), sizeof(maze->numpart));
  932.                      /* Number of parts */
  933.     for(i=0;i<maze->numpart;i++) {
  934.         pt = maze->parts[i];
  935.  
  936.         /* First, write the map */
  937.  
  938.         Write(fd, &(pt->halign), sizeof(pt->halign));
  939.         Write(fd, &(pt->valign), sizeof(pt->valign));
  940.         Write(fd, &(pt->xsize), sizeof(pt->xsize));
  941.         Write(fd, &(pt->ysize), sizeof(pt->ysize));
  942.         for(j=0;j<pt->ysize;j++) {
  943.         if(!maze->init_lev.init_present ||
  944.            pt->xsize > 1 || pt->ysize > 1)
  945.             Write(fd, pt->map[j], sizeof(*(pt->map[j])) * pt->xsize);
  946.         Free(pt->map[j]);
  947.         }
  948.         Free(pt->map);
  949.  
  950.         /* level region stuff */
  951.         Write(fd, &(pt->nlreg), sizeof(pt->nlreg));
  952.         for(j=0;j<pt->nlreg;j++) {
  953.             Write(fd, pt->lregions[j], sizeof(lev_region));
  954.             if(pt->lregions[j]->rname) {
  955.                 char c = strlen(pt->lregions[j]->rname);
  956.                 Write(fd, &c, sizeof(c));
  957.                 Write(fd, pt->lregions[j]->rname, (int)c);
  958.             }
  959.             Free(pt->lregions[j]);
  960.         }
  961.         if(pt->nlreg > 0)
  962.             Free(pt->lregions);
  963.  
  964.         /* The random registers */
  965.         Write(fd, &(pt->nrobjects), sizeof(pt->nrobjects));
  966.         if(pt->nrobjects) {
  967.             Write(fd, pt->robjects, pt->nrobjects);
  968.             Free(pt->robjects);
  969.         }
  970.         Write(fd, &(pt->nloc), sizeof(pt->nloc));
  971.         if(pt->nloc) {
  972.             Write(fd, pt->rloc_x, pt->nloc);
  973.             Write(fd, pt->rloc_y, pt->nloc);
  974.             Free(pt->rloc_x);
  975.             Free(pt->rloc_y);
  976.         }
  977.         Write(fd, &(pt->nrmonst), sizeof(pt->nrmonst));
  978.         if(pt->nrmonst) {
  979.             Write(fd, pt->rmonst, pt->nrmonst);
  980.             Free(pt->rmonst);
  981.         }
  982.  
  983.         /* subrooms */
  984.         Write(fd, &(pt->nreg), sizeof(pt->nreg));
  985.         for(j=0;j<pt->nreg;j++) {
  986.             Write(fd, pt->regions[j], sizeof(region));
  987.             Free(pt->regions[j]);
  988.         }
  989.         if(pt->nreg > 0)
  990.             Free(pt->regions);
  991.  
  992.         /* the doors */
  993.         Write(fd, &(pt->ndoor), sizeof(pt->ndoor));
  994.         for(j=0;j<pt->ndoor;j++) {
  995.             Write(fd, pt->doors[j], sizeof(door));
  996.             Free(pt->doors[j]);
  997.         }
  998.         if (pt->ndoor > 0)
  999.             Free(pt->doors);
  1000.  
  1001.         /* The traps */
  1002.         Write(fd, &(pt->ntrap), sizeof(pt->ntrap));
  1003.         for(j=0;j<pt->ntrap;j++) {
  1004.             Write(fd, pt->traps[j], sizeof(trap));
  1005.             Free(pt->traps[j]);
  1006.         }
  1007.         if (pt->ntrap)
  1008.             Free(pt->traps);
  1009.  
  1010.         /* The monsters */
  1011.         Write(fd, &(pt->nmonster), sizeof(pt->nmonster));
  1012.         for(j=0;j<pt->nmonster;j++) {
  1013.             short size;
  1014.             monster *m = pt->monsters[j];
  1015.             Write(fd, m, sizeof(monster));
  1016.             size = m->name ? strlen(m->name) : 0;
  1017.             Write(fd, &size, sizeof(size));
  1018.             if (size) {
  1019.                 Write(fd, m->name, size);
  1020.                 Free(m->name);
  1021.             }
  1022.             size = m->appear_as ? strlen(m->appear_as) : 0;
  1023.             Write(fd, &size, sizeof(size));
  1024.             if (size) {
  1025.                 Write(fd, m->appear_as, size);
  1026.                 Free(m->appear_as);
  1027.             }
  1028.             Free(pt->monsters[j]);
  1029.         }
  1030.         if (pt->nmonster > 0)
  1031.             Free(pt->monsters);
  1032.  
  1033.         /* The objects */
  1034.         Write(fd, &(pt->nobject), sizeof(pt->nobject));
  1035.         for(j=0;j<pt->nobject;j++) {
  1036.             short size;
  1037.             object *o = pt->objects[j];
  1038.             Write(fd, o, sizeof(object));
  1039.             size = o->name ? strlen(o->name) : 0;
  1040.             Write(fd, &size, sizeof(size));
  1041.             if (size) {
  1042.                 Write(fd, o->name, size);
  1043.                 Free(o->name);
  1044.             }
  1045.             Free(pt->objects[j]);
  1046.         }
  1047.         if(pt->nobject > 0)
  1048.             Free(pt->objects);
  1049.  
  1050.         /* The drawbridges */
  1051.         Write(fd, &(pt->ndrawbridge), sizeof(pt->ndrawbridge));
  1052.         for(j=0;j<pt->ndrawbridge;j++) {
  1053.             Write(fd, pt->drawbridges[j], sizeof(drawbridge));
  1054.             Free(pt->drawbridges[j]);
  1055.         }
  1056.         if(pt->ndrawbridge > 0)
  1057.             Free(pt->drawbridges);
  1058.  
  1059.         /* The mazewalk directives */
  1060.         Write(fd, &(pt->nwalk), sizeof(pt->nwalk));
  1061.         for(j=0; j<pt->nwalk; j++) {
  1062.             Write(fd, pt->walks[j], sizeof(walk));
  1063.             Free(pt->walks[j]);
  1064.         }
  1065.         if (pt->nwalk > 0)
  1066.             Free(pt->walks);
  1067.  
  1068.         /* The non_diggable directives */
  1069.         Write(fd, &(pt->ndig), sizeof(pt->ndig));
  1070.         for(j=0;j<pt->ndig;j++) {
  1071.             Write(fd, pt->digs[j], sizeof(digpos));
  1072.             Free(pt->digs[j]);
  1073.         }
  1074.         if (pt->ndig > 0)
  1075.             Free(pt->digs);
  1076.  
  1077.         /* The non_passwall directives */
  1078.         Write(fd, &(pt->npass), sizeof(pt->npass));
  1079.         for(j=0;j<pt->npass;j++) {
  1080.             Write(fd, pt->passs[j], sizeof(digpos));
  1081.             Free(pt->passs[j]);
  1082.         }
  1083.         if (pt->npass > 0)
  1084.             Free(pt->passs);
  1085.  
  1086.         /* The ladders */
  1087.         Write(fd, &(pt->nlad), sizeof(pt->nlad));
  1088.         for(j=0;j<pt->nlad;j++) {
  1089.             Write(fd, pt->lads[j], sizeof(lad));
  1090.             Free(pt->lads[j]);
  1091.         }
  1092.         if (pt->nlad > 0)
  1093.             Free(pt->lads);
  1094.  
  1095.         /* The stairs */
  1096.         Write(fd, &(pt->nstair), sizeof(pt->nstair));
  1097.         for(j=0;j<pt->nstair;j++) {
  1098.             Write(fd, pt->stairs[j], sizeof(stair));
  1099.             Free(pt->stairs[j]);
  1100.         }
  1101.         if (pt->nstair > 0)
  1102.             Free(pt->stairs);
  1103.  
  1104.         /* The altars */
  1105.         Write(fd, &(pt->naltar), sizeof(pt->naltar));
  1106.         for(j=0;j<pt->naltar;j++) {
  1107.             Write(fd, pt->altars[j], sizeof(altar));
  1108.             Free(pt->altars[j]);
  1109.         }
  1110.         if (pt->naltar > 0)
  1111.             Free(pt->altars);
  1112.  
  1113.         /* The gold piles */
  1114.         Write(fd, &(pt->ngold), sizeof(pt->naltar));
  1115.         for(j=0;j<pt->ngold;j++) {
  1116.             Write(fd, pt->golds[j], sizeof(gold));
  1117.             Free(pt->golds[j]);
  1118.         }
  1119.         if (pt->ngold > 0)
  1120.             Free(pt->golds);
  1121.  
  1122.         /* The engravings */
  1123.         Write(fd, &(pt->nengraving), sizeof(pt->nengraving));
  1124.         for(j=0;j<pt->nengraving;j++) {
  1125.             char *txt;
  1126.             int size;
  1127.             txt = pt->engravings[j]->e.text;
  1128.             size = pt->engravings[j]->e.length = strlen(txt);
  1129.             Write(fd, pt->engravings[j], sizeof *pt->engravings[j]);
  1130.             Write(fd, txt, size);
  1131.             Free(txt);
  1132.             Free(pt->engravings[j]);
  1133.         }
  1134.         if (pt->nengraving > 0)
  1135.             Free(pt->engravings);
  1136.  
  1137.         /* The fountains */
  1138.         Write(fd, &(pt->nfountain), sizeof(pt->nfountain));
  1139.         for(j=0;j<pt->nfountain;j++) {
  1140.         Write(fd, pt->fountains[j], sizeof(fountain));
  1141.         Free(pt->fountains[j]);
  1142.         }
  1143.         if (pt->nfountain > 0)
  1144.             Free(pt->fountains);
  1145.  
  1146.         Free(pt);
  1147.     }
  1148. }
  1149.  
  1150. /*
  1151.  * Here we write the structure of the room level in the specified file (fd).
  1152.  */
  1153.  
  1154. void
  1155. write_lev(fd, lev)
  1156. int fd;
  1157. splev *lev;
  1158. {
  1159.     short i,j, size;
  1160.     room *pt;
  1161.  
  1162.     write_common_data(fd, SP_LEV_ROOMS, &(lev->init_lev), lev->flags);
  1163.  
  1164.     /* Random registers */
  1165.  
  1166.     Write(fd, &lev->nrobjects, sizeof(lev->nrobjects));
  1167.     if (lev->nrobjects) {
  1168.         Write(fd, lev->robjects, lev->nrobjects);
  1169.         Free (lev->robjects);
  1170.     }
  1171.     Write(fd, &lev->nrmonst, sizeof(lev->nrmonst));
  1172.     if (lev->nrmonst) {
  1173.         Write(fd, lev->rmonst, lev->nrmonst);
  1174.         Free (lev->rmonst);
  1175.     }
  1176.  
  1177.     Write(fd, &(lev->nroom), sizeof(lev->nroom));
  1178.                             /* Number of rooms */
  1179.     for(i=0;i<lev->nroom;i++) {
  1180.         pt = lev->rooms[i];
  1181.  
  1182.         /* Room characteristics */
  1183.  
  1184.         if (pt->name)
  1185.             size = strlen(pt->name);
  1186.         else
  1187.             size = 0;
  1188.         Write(fd, &size, sizeof(size));
  1189.         if (size)
  1190.             Write(fd, pt->name, size);
  1191.  
  1192.         if (pt->parent)
  1193.             size = strlen(pt->parent);
  1194.         else
  1195.             size = 0;
  1196.         Write(fd, &size, sizeof(size));
  1197.         if (size)
  1198.             Write(fd, pt->parent, size);
  1199.  
  1200.         Write(fd, &(pt->x), sizeof(pt->x));
  1201.         Write(fd, &(pt->y), sizeof(pt->y));
  1202.         Write(fd, &(pt->w), sizeof(pt->w));
  1203.         Write(fd, &(pt->h), sizeof(pt->h));
  1204.         Write(fd, &(pt->xalign), sizeof(pt->xalign));
  1205.         Write(fd, &(pt->yalign), sizeof(pt->yalign));
  1206.         Write(fd, &(pt->rtype), sizeof(pt->rtype));
  1207.         Write(fd, &(pt->chance), sizeof(pt->chance));
  1208.         Write(fd, &(pt->rlit), sizeof(pt->rlit));
  1209.         Write(fd, &(pt->filled), sizeof(pt->filled));
  1210.  
  1211.         /* the doors */
  1212.         Write(fd, &(pt->ndoor), sizeof(pt->ndoor));
  1213.         for(j=0;j<pt->ndoor;j++)
  1214.             Write(fd, pt->doors[j], sizeof(room_door));
  1215.         /* The traps */
  1216.         Write(fd, &(pt->ntrap), sizeof(pt->ntrap));
  1217.         for(j=0;j<pt->ntrap;j++)
  1218.             Write(fd, pt->traps[j], sizeof(trap));
  1219.  
  1220.         /* The monsters */
  1221.         Write(fd, &(pt->nmonster), sizeof(pt->nmonster));
  1222.         for(j=0;j<pt->nmonster;j++) {
  1223.             monster *m = pt->monsters[j];
  1224.             Write(fd, m, sizeof(monster));
  1225.             size = m->name ? strlen(m->name) : 0;
  1226.             Write(fd, &size, sizeof(size));
  1227.             if (size)
  1228.                 Write(fd, m->name, size);
  1229.             size = m->appear_as ? strlen(m->appear_as) : 0;
  1230.             Write(fd, &size, sizeof(size));
  1231.             if (size)
  1232.                 Write(fd, m->appear_as, size);
  1233.         }
  1234.  
  1235.         /* The objects */
  1236.         Write(fd, &(pt->nobject), sizeof(pt->nobject));
  1237.         for(j=0;j<pt->nobject;j++) {
  1238.             object *o = pt->objects[j];
  1239.             Write(fd, o, sizeof(object));
  1240.             size = o->name ? strlen(o->name) : 0;
  1241.             Write(fd, &size, sizeof(size));
  1242.             if (size)
  1243.                 Write(fd,  o->name, size);
  1244.         }
  1245.  
  1246.         /* The stairs */
  1247.         Write(fd, &(pt->nstair), sizeof(pt->nstair));
  1248.         for(j=0;j<pt->nstair;j++)
  1249.             Write(fd, pt->stairs[j], sizeof(stair));
  1250.  
  1251.         /* The altars */
  1252.         Write(fd, &(pt->naltar), sizeof(pt->naltar));
  1253.         for(j=0;j<pt->naltar;j++)
  1254.             Write(fd, pt->altars[j], sizeof(altar));
  1255.  
  1256.         /* The gold piles */
  1257.         Write(fd, &(pt->ngold), sizeof(pt->ngold));
  1258.         for(j=0;j<pt->ngold;j++)
  1259.             Write(fd, pt->golds[j], sizeof(gold));
  1260.  
  1261.         /* The engravings */
  1262.         Write(fd, &(pt->nengraving), sizeof(pt->nengraving));
  1263.         for(j=0;j<pt->nengraving;j++) {
  1264.             char *txt;
  1265.             txt = pt->engravings[j]->e.text;
  1266.             size = pt->engravings[j]->e.length = strlen(txt);
  1267.             Write(fd, pt->engravings[j],
  1268.                   sizeof *pt->engravings[j]);
  1269.             Write(fd, txt, size);
  1270.         }
  1271.  
  1272.         /* The fountains */
  1273.         Write(fd, &(pt->nfountain), sizeof(pt->nfountain));
  1274.         for(j=0;j<pt->nfountain;j++)
  1275.             Write(fd, pt->fountains[j], sizeof(fountain));
  1276.  
  1277.         /* The sinks */
  1278.         Write(fd, &(pt->nsink), sizeof(pt->nsink));
  1279.         for(j=0;j<pt->nsink;j++)
  1280.             Write(fd, pt->sinks[j], sizeof(sink));
  1281.  
  1282.         /* The pools */
  1283.         Write(fd, &(pt->npool), sizeof(pt->npool));
  1284.         for(j=0;j<pt->npool;j++)
  1285.             Write(fd, pt->pools[j], sizeof(pool));
  1286.     }
  1287.  
  1288.     /* The corridors */
  1289.     Write(fd, &ncorridor, sizeof(ncorridor));
  1290.     for (i=0; i<ncorridor; i++) {
  1291.         Write(fd, tmpcor[i], sizeof(corridor));
  1292.         Free(tmpcor[i]);
  1293.     }
  1294.     ncorridor = 0;
  1295. }
  1296.  
  1297. void
  1298. free_rooms(ro, n)
  1299. room **ro;
  1300. int n;
  1301. {
  1302.     short j;
  1303.     room *r;
  1304.  
  1305.     while(n--) {
  1306.         r = ro[n];
  1307.         Free(r->name);
  1308.         Free(r->parent);
  1309.         if ((j = r->ndoor) != 0) {
  1310.             while(j--)
  1311.                 Free(r->doors[j]);
  1312.             Free(r->doors);
  1313.         }
  1314.         if ((j = r->ntrap) != 0) {
  1315.             while (j--)
  1316.                 Free(r->traps[j]);
  1317.             Free(r->traps);
  1318.         }
  1319.         if ((j = r->nmonster) != 0) {
  1320.             while (j--) {
  1321.                 Free(r->monsters[j]->name);
  1322.                 Free(r->monsters[j]->appear_as);
  1323.                 Free(r->monsters[j]);
  1324.             }
  1325.             Free(r->monsters);
  1326.         }
  1327.         if ((j = r->nobject) != 0) {
  1328.             while(j--) {
  1329.                 Free(r->objects[j]->name);
  1330.                 Free(r->objects[j]);
  1331.             }
  1332.             Free(r->objects);
  1333.         }
  1334.         if ((j = r->nstair) != 0) {
  1335.             while(j--)
  1336.                 Free(r->stairs[j]);
  1337.             Free(r->stairs);
  1338.         }
  1339.         if ((j = r->naltar) != 0) {
  1340.             while (j--)
  1341.                 Free(r->altars[j]);
  1342.             Free(r->altars);
  1343.         }
  1344.         if ((j = r->ngold) != 0) {
  1345.             while(j--)
  1346.                 Free(r->golds[j]);
  1347.             Free(r->golds);
  1348.         }
  1349.         if ((j = r->nengraving) != 0) {
  1350.             while(j--) {
  1351.                 Free(r->engravings[j]->e.text);
  1352.                 Free(r->engravings[j]);
  1353.             }
  1354.             Free(r->engravings);
  1355.         }
  1356.         if ((j = r->nfountain) != 0) {
  1357.             while(j--)
  1358.                 Free(r->fountains[j]);
  1359.             Free(r->fountains);
  1360.         }
  1361.         if ((j = r->nsink) != 0) {
  1362.             while(j--)
  1363.                 Free(r->sinks[j]);
  1364.             Free(r->sinks);
  1365.         }
  1366.         if ((j = r->npool) != 0) {
  1367.             while(j--)
  1368.                 Free(r->pools[j]);
  1369.             Free(r->pools);
  1370.         }
  1371.         Free(r);
  1372.     }
  1373. }
  1374.  
  1375. #ifdef STRICT_REF_DEF
  1376. /*
  1377.  * Any globals declared in hack.h and descendents which aren't defined
  1378.  * in the modules linked into lev_comp should be defined here.  These
  1379.  * definitions can be dummies:  their sizes shouldn't matter as long as
  1380.  * as their types are correct; actual values are irrelevant.
  1381.  */
  1382. #define ARBITRARY_SIZE 1
  1383. /* attrib.c */
  1384. struct attribs attrmax, attrmin;
  1385. /* files.c */
  1386. const char *configfile;
  1387. char lock[ARBITRARY_SIZE];
  1388. char SAVEF[ARBITRARY_SIZE];
  1389. # ifdef MICRO
  1390. char SAVEP[ARBITRARY_SIZE];
  1391. # endif
  1392. /* termcap.c */
  1393. struct tc_lcl_data tc_lcl_data;
  1394. # ifdef TEXTCOLOR
  1395. #  ifdef TOS
  1396. const char *hilites[MAXCOLORS];
  1397. #  else
  1398. char NEARDATA *hilites[MAXCOLORS];
  1399. #  endif
  1400. # endif
  1401. /* trap.c */
  1402. const char *traps[TRAPNUM];
  1403. /* window.c */
  1404. struct window_procs windowprocs;
  1405. /* xxxtty.c */
  1406. # ifdef DEFINE_OSPEED
  1407. short ospeed;
  1408. # endif
  1409. #endif    /* STRICT_REF_DEF */
  1410.  
  1411. /*lev_main.c*/
  1412.